#include <iostream>
#include <string>
#include "Log.hpp"
#include "Sock.hpp"
#include "Err.hpp"
#include <pthread.h>
#include <functional>
using namespace std;

using func_t = function<string(string &)>; // 和typedef一样的功能，为业务处理而生

class HttpServer;

// 真正通信时，创建线程传递的参数
class ThreadData
{
public:
    ThreadData(string clientip, uint16_t clientport, HttpServer *server, int sock)
        : _clientip(clientip),
          _clientport(clientport),
          _server(server), _sock(sock)
    {
    }

    string _clientip;     // 客户端IP
    uint16_t _clientport; // 客户端port
    HttpServer *_server;  // 服务器指针
    int _sock;            // 通信用的套接字
};

class HttpServer
{
public:
    // 构造
    HttpServer(uint16_t port, func_t func)
        : _port(port), _func(func)
    {
    }

    // 初始化，完成通信前的基本操作
    void Init()
    {
        _listensock.Socket();
        _listensock.Bind(_port);
        _listensock.Listen();
    }

    // 正式开始接受客户端
    void Start()
    {
        while (1)
        {
            // sleep(1);
            string clientip;
            uint16_t clientport;
            //获取真正通信的套接字，并把客户端的信息拿到
            int sock = _listensock.Accept(clientip, clientport);
            if (sock < 0)
            {
                continue;
            }

            //创建线程，将真正的通信交给线程去做
            pthread_t tid;
            ThreadData *data = new ThreadData(clientip, clientport, this, sock);
            pthread_create(&tid, nullptr, Routine, data);
        }
    }

    //套一层，通过Routine来调用HandlerHttpRequest来进行通信
    static void *Routine(void *arg)
    {
        //和主线程脱离，线程运行结束不需要主进程进行等待
        pthread_detach(pthread_self());
        ThreadData *data = static_cast<ThreadData *>(arg);
        //调用真正进行通信的函数
        data->_server->HandlerHttpRequest(data->_sock);
        close(data->_sock);
        delete data;
        return nullptr;
    }

    void HandlerHttpRequest(int sock)
    {
        // while(1)
        {
            char buff[2048];
            //获取请求
            int n = recv(sock, buff, sizeof(buff) - 1, 0);//可能一次读不完，但是默认读完
            if (n > 0)
            {
                //设置\0
                buff[n] = 0;
                //处理请求
                string request(buff);
                string repsonse = _func(request);
                //响应回客户端
                send(sock, repsonse.c_str(), repsonse.size(), 0);
            }
            else
            {
                LogMessage(Information, "client quit...");
                // break;
            }
        }
    }



private:
    Sock _listensock;
    uint16_t _port;
    func_t _func;
};
